/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pa165.bookingmanager.services.impl;

import cz.muni.fi.pa165.bookingmanager.dao.ReservationManager;
import cz.muni.fi.pa165.bookingmanager.entities.Hotel;
import cz.muni.fi.pa165.bookingmanager.entities.Reservation;
import cz.muni.fi.pa165.bookingmanager.entities.Room;
import cz.muni.fi.pa165.bookingmanager.exceptions.IllegalOrphanException;
import cz.muni.fi.pa165.bookingmanager.exceptions.NonexistentEntityException;
import cz.muni.fi.pa165.bookingmanager.exceptions.PreexistingEntityException;
import cz.muni.fi.pa165.bookingmanager.interceptors.LoggingInterceptor;
import cz.muni.fi.pa165.bookingmanager.interceptors.ShiroSecuredInterceptor;
import cz.muni.fi.pa165.bookingmanager.other.PaymentStatusEnum;
import cz.muni.fi.pa165.bookingmanager.services.ReservationService;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import org.apache.shiro.authz.annotation.RequiresRoles;

/**
 *
 * @author Daniel Sák, 374560
 */
@Stateless
public class ReservationServiceImpl implements ReservationService {

    @EJB
    private ReservationManager reservationManager;
    @Resource
    private SessionContext ctx;

    @Override
    @Interceptors({ShiroSecuredInterceptor.class, LoggingInterceptor.class})
    @RequiresRoles("receptionist")
    public void createReservation(Reservation reservation) throws IllegalOrphanException, PreexistingEntityException {
        if (!isValidEntity(reservation)) {
            throw new IllegalArgumentException("Invalid Reservation entity");
        }
        try {
            reservationManager.createReservation(reservation);
        } catch (Exception ex) {
            Logger.getLogger(ReservationServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            ctx.setRollbackOnly();
        }
    }

    @Override
    @Interceptors({ShiroSecuredInterceptor.class, LoggingInterceptor.class})
    @RequiresRoles("receptionist")
    public void updateReservation(Reservation reservation) throws IllegalOrphanException, NonexistentEntityException {
        if (!isValidEntity(reservation)) {
            throw new IllegalArgumentException("Invalid Reservation entity");
        }
        try {
            reservationManager.updateReservation(reservation);
        } catch (Exception ex) {
            Logger.getLogger(ReservationServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            ctx.setRollbackOnly();
        }
    }

    @Override
    @Interceptors({ShiroSecuredInterceptor.class, LoggingInterceptor.class})
    @RequiresRoles("receptionist")
    public void deleteReservation(Reservation reservation) throws IllegalOrphanException, NonexistentEntityException {
        if (!isValidEntity(reservation)) {
            throw new IllegalArgumentException("Invalid Reservation entity");
        }
        try {
            reservationManager.deleteReservation(reservation);
        } catch (Exception ex) {
            Logger.getLogger(ReservationServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            ctx.setRollbackOnly();
        }
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public Reservation getResevationByID(Long resId) {
        Reservation reservation = reservationManager.getResevationByID(resId);
        return reservation;
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public List<Reservation> findAllHotelReservations(Hotel hotel) {
        List<Reservation> reservations = reservationManager.findAllHotelReservations(hotel.getId());
        return reservations;
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public List<Reservation> findAllRoomReservations(Room room) {
        List<Reservation> reservations = reservationManager.findAllRoomReservations(room.getId());
        return reservations;
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public List<Reservation> findAllHotelReservations(Hotel hotel, Date startDate) {
        List<Reservation> reservations = reservationManager.findAllHotelReservations(hotel.getId(), startDate);
        return reservations;
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public List<Reservation> findAllRoomReservations(Room room, Date startDate) {
        List<Reservation> reservations = reservationManager.findAllRoomReservations(room.getId(), startDate);
        return reservations;
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public List<Reservation> findAllReservationsByPaid(PaymentStatusEnum paid) {
        List<Reservation> reservations = reservationManager.findAllReservationsByPaid(paid);
        return reservations;
    }

    private boolean isValidEntity(Reservation reservation) {
        if (reservation == null) {
            return false;
        }

        if (reservation.getCustomers() == null) {
            return false;
        }

        if (reservation.getDuration() <= 0) {
            return false;
        }

        if (reservation.getHotel() == null) {
            return false;
        }

        if (reservation.getRoom() == null) {
            return false;
        }


        if (reservation.getStartDate() == null) {
            return false;
        }

        if (reservation.getTotalPrice() == null || reservation.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0) {
            return false;
        }

        if (reservation.isPaid() == null) {
            return false;
        }

        return true;
    }

    public void setReservationManager(ReservationManager resManager) {
        this.reservationManager = resManager;
    }
}
